package com.linden.std.aspect;

import com.linden.std.annotation.RequiresPermissions;
import com.linden.std.domain.vo.UserVO;
import com.linden.std.enums.ExceptionEnums;
import com.linden.std.exception.CustomException;
import com.linden.std.Utils.UserContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * 权限校验切面
 */
@Slf4j
@Aspect
@Component
@Order(2)
public class PermissionAspect {

    @Around("@annotation(requiresPermissions)")
    public Object checkPermission(ProceedingJoinPoint joinPoint, RequiresPermissions requiresPermissions) throws Throwable {
        
        UserVO currentUser = UserContextUtil.getUser();
        if (currentUser == null) {
            log.warn("用户上下文为空，访问拒绝");
            throw new CustomException(ExceptionEnums.UNAUTHORIZED);
        }
        
        String[] requiredPermissions = requiresPermissions.value();
        log.debug("检查用户{}的权限，需要权限: {}", currentUser.getAccount(), Arrays.toString(requiredPermissions));
        
        if (requiredPermissions.length == 0) {
            return joinPoint.proceed();
        }
        
        List<String> userPermissions = currentUser.getPermCodes();
        log.debug("用户{}当前权限: {}", currentUser.getAccount(), userPermissions);
        
        if (userPermissions == null || userPermissions.isEmpty()) {
            log.warn("用户{}没有任何权限", currentUser.getAccount());
            throw new CustomException(ExceptionEnums.ACCESS_DENIED);
        }
        
        boolean hasPermission = false;
        if (requiresPermissions.logical() == RequiresPermissions.Logical.AND) {
            // 需要拥有所有权限
            hasPermission = Arrays.stream(requiredPermissions)
                .allMatch(userPermissions::contains);
        } else {
            // 只需要拥有其中一个权限
            hasPermission = Arrays.stream(requiredPermissions)
                .anyMatch(userPermissions::contains);
        }
        
        if (!hasPermission) {
            log.warn("用户{}缺少权限: {}，当前权限: {}", 
                    currentUser.getAccount(), 
                    Arrays.toString(requiredPermissions), 
                    userPermissions);
            throw new CustomException(ExceptionEnums.ACCESS_DENIED);
        }
        
        log.debug("用户{}权限检查通过", currentUser.getAccount());
        return joinPoint.proceed();
    }
}